package com.zhj.psi.core.tools;

import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 */
public class DateUtils extends org.apache.commons.lang.time.DateUtils {
	
	
	
	static Logger logger = LoggerFactory.getLogger(DateUtils.class);

	public static final int MILLIS_IN_SECOND = 1000;
	public static final int MILLIS_IN_MINUTE = 60 * 1000;
	public static final int MILLIS_IN_HOUR = 60 * 60 * 1000;
	public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
	// --------- special format and parse method --------------
	public static final String DATE_ISO_FORMAT = "yyyy-MM-dd";
	public static final String DATE_FORMAT = "000000";
	public static final String TIME_ISO_FORMAT = "HH:mm:ss";
	public static final String DATETIME_ISO_FORMAT = "yyyy-MM-dd HH:mm:ss";
	public static final String DATE_COMPACT_FORMAT = "yyyyMMdd";
	public static final String TIME_COMPACT_FORMAT = "HHmmss";
	public static final String DATETIME_COMPACT_FORMAT = "yyyyMMddHHmmss";
	public static final String DATETIME_SYSKEY_FORMAT = "yyyyMMddHHmmssSSS";
	/**
	 * 校验日期字符串是否为yyyy-MM-dd
	 */
	public static final String DATE_ISO_PARTEN ="^((\\d{2}(([02468][048])|([13579][26]))[\\-\\-\\s]?((((0?[13578])|(1[02]))[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\-\\s]?((((0?[13578])|(1[02]))[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))" +"[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\-\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
	public static final String DATETIME_ISO_PARTEN ="^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$";
	public static  Date toDate(String str,String pattern){
		SimpleDateFormat sdf=null;
		if(pattern.equals(DATE_COMPACT_FORMAT))
			sdf=(SimpleDateFormat) getDateFormat(DATE_COMPACT_FORMAT);
		else if(pattern.equals(DATETIME_COMPACT_FORMAT)){
			sdf=(SimpleDateFormat) getDateFormat(DATETIME_COMPACT_FORMAT);
		}
			
		else{
			sdf = getDateFormat(pattern);
		}
		try {
			return    sdf.parse(str) ;
		} catch (Exception e) {
       //log.warn(e);
      // e.printStackTrace();
      // log.error("input:"+str+" pattern:"+pattern);
         return null;
		}
	}
	
	public DateUtils() {
	}
	public static java.sql.Date getCurrentDate(){
		return new java.sql.Date(System.currentTimeMillis());
	}
	
	/**
	 * 获取现在时间
	 * @author zhuhuijun
	 * @return 返回时间类型 yyyy-MM-dd HH:mm:ss
	 */
	public static Date getNowDate() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		return parse(dateString, DATETIME_ISO_FORMAT);
	}
	/**
	 * @author zhuhuijun
	 * @return yyyy-MM-dd 获取现在时间
	 * @return返回短时间格式 yyyy-MM-dd
	 */
	public static Date getNowDateShort() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		return parse(dateString, DATE_ISO_FORMAT);
	}
	
	/**
	 * 获取现在时间
	 * @author zhuhuijun
	 * @return返回字符串格式 yyyy-MM-dd HH:mm:ss
	 */
	public static String getStringDate() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		return dateString;
	}
	
	/**
	 * 获取现在时间
	 * @author zhuhuijun
	 * @return 返回短时间字符串格式yyyy-MM-dd
	 */
	public static String getStringDateShort() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		return dateString;
	}
	/**
	 * 获取现在时间
	 * @author zhuhuijun
	 * @return 返回短时间字符串格式yyyy-MM-dd HH:MM
	 */
	public static String getStringDateShortmm() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HHmm");
		String dateString = formatter.format(currentTime);
		return dateString;
	}

	/**
	 * 获取时间 小时:分;秒 HH:mm:ss
	 * @author zhuhuijun
	 * @return 
	 */
	public static String getTimeShort() {
		SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
		Date currentTime = new Date();
		String dateString = formatter.format(currentTime);
		return dateString;
	}

	/**
	 * 将长时间格式字符串(2015-12-09 17:14:04)转换为时间 yyyy-MM-dd HH:mm:ss
	 * @author zhuhuijun
	 * @param strDate
	 * @return
	 */
	public static Date strToDateLong(String strDate) {
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		ParsePosition pos = new ParsePosition(0);
		Date strtodate = formatter.parse(strDate, pos);
		return strtodate;
	}

	/**
	 * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
	 * @author zhuhuijun
	 * @param dateDate
	 * @return
	 */
	public static String dateToStrLong(Date dateDate) {
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String dateString = formatter.format(dateDate);
		return dateString;
	}

	/**
	 * 将短时间格式时间转换为字符串 yyyy-MM-dd
	 * @author zhuhuijun
	 * @param dateDate
	 * @param k
	 * @return
	 */
	public static String dateToStr(Date dateDate) {
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		String dateString = formatter.format(dateDate);
		return dateString;
	}

	/**
	 * 将短时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
	 * @author zhuhuijun
	 * @param strDate
	 * @return
	 */
	public static Date strToDate(String strDate) {
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		ParsePosition pos = new ParsePosition(0);
		Date strtodate = formatter.parse(strDate, pos);
		return strtodate;
	}

	/**
	 * 得到现在时间
	 * @author zhuhuijun
	 * @return
	 */
	public static Date getNow() {
		Date currentTime = new Date();
		return currentTime;
	}
	
	/**
	 * 提取一个月中的最后一天
	 * @author zhuhuijun
	 * @param day
	 * @return
	 */
	public static Date getLastDate(long day) {
		Date date = new Date();
		long date_3_hm = date.getTime() - 3600000 * 34 * day;
		Date date_3_hm_date = new Date(date_3_hm);
		return date_3_hm_date;
	}

	/**
	 * 得到现在时间
	 * @author zhuhuijun
	 * @return 字符串 yyyyMMdd HHmmss
	 */
	public static String getStringToday() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd HHmmss");
		String dateString = formatter.format(currentTime);
		return dateString;
	}

	/**
	 * 得到现在时间
	 * @author zhuhuijun
	 * @return 字符串 yyyyMMdd HH:mm:ss
	 */
	public static String getStringTodayA() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_COMPACT_FORMAT);
		String dateString = formatter.format(currentTime);
		return dateString;
	}

	/**
	 * @author zhuhuijun
	 * 得到现在小时
	 */
	public static String getHour() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		String hour;
		hour = dateString.substring(11, 13);
		return hour;
	}

	/**
	 * @author zhuhuijun
	 * 得到现在分钟
	 * @return
	 */
	public static String getTime() {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String dateString = formatter.format(currentTime);
		String min;
		min = dateString.substring(14, 16);
		return min;
	}
	/**
	 * @author zhuhuijun
	 * 得到一个时间延后或前移几天的时间,nowdate为时间,delay(-3为前移3天，3为后延3天)为前移或后延的天数
	 */
	public static String getNextDay(String nowdate, String delay) {
		SimpleDateFormat format = new SimpleDateFormat(DATE_ISO_FORMAT);
		String mdate = "";
		Date d = strToDate(nowdate);
		long myTime = (d.getTime() / 1000) + Integer.parseInt(delay) * 24 * 60 * 60;
		d.setTime(myTime * 1000);
		mdate = format.format(d);
		return mdate;
	}
	/**
	 * 
	 * 得到一个时间延后或前移几天的时间,nowdate为时间,delay(-3为前移3天，3为后延3天)为前移或后延的天数
	 */
	public static Date getNextDay(Date nowdate, int delay) {
		Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(nowdate);
        rightNow.add(Calendar.DAY_OF_MONTH,delay);
        return rightNow.getTime();
	}
	/**
	 * @author zhuhuijun
	 * 时间前推或后推分钟,其中JJ表示分钟.
	 */
	public static String getPreTime(String sj1, String jj) {
		SimpleDateFormat format = new SimpleDateFormat(DATETIME_ISO_FORMAT);
		String mydate1 = "";
		try {
			Date date1 = format.parse(sj1);
			long Time = (date1.getTime() / 1000) + Integer.parseInt(jj) * 60;
			date1.setTime(Time * 1000);
			mydate1 = format.format(date1);
		} catch (Exception e) {
		}
		return mydate1;
	}
	
	/**
	 * 两个时间之间的天数
	 * @author zhuhuijun
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static long getDays(String date1, String date2) {
		if (date1 == null || date1.equals(""))
			return 0;
		if (date2 == null || date2.equals(""))
			return 0;
		// 转换为标准时间
		SimpleDateFormat myFormatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		Date date = null;
		Date mydate = null;
		try {
			date = myFormatter.parse(date1);
			mydate = myFormatter.parse(date2);
		} catch (Exception e) {
		}
		long day = (date.getTime() - mydate.getTime()) / (24 * 60 * 60 * 1000);
		return day;
	}

	public static long getDays(Date date1, Date date2) {
		return DateUtils.getDays(DateUtils.dateToStrLong(date1),DateUtils.dateToStrLong(date2));
	}

	/**
	 * 取得数据库主键 生成格式为yyyymmddhhmmss+k位随机数
	 * 表示是取几位随机数，可以自己定
	 */
	static List<String> randList = new ArrayList<String>();
	/**
	 * @author zhuhuijun
	 * 保证一次产生10000个随机数内无重复 平均一秒钟能产生250个随机数
	 */
	public static String getNo(int k) {
		if (randList.size() > 10000) {
			randList.clear();
		}
		String rno = getNoNo(k);
		while (randList.contains(rno)) {

			rno = getNoNo(k);

		}
		randList.add(rno);
		return rno;
	}
	/**
	 * 根据用户传入的时间表示格式，返回当前时间的格式 如果是yyyyMMdd，注意字母y不能大写。
	 * 
	 * @param sformat
	 *            yyyyMMddhhmmss
	 * @return
	 */
	public static String getUserDate(String sformat) {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat(sformat);
		String dateString = formatter.format(currentTime);
		return dateString;
	}
	
	private static String getNoNo(int k) {
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return getUserDate(DATETIME_COMPACT_FORMAT) + RandomStringUtils.randomNumeric(k);
	}
	/**
	 * 形成如下的日历 ， 根据传入的一个时间返回一个结构 星期日 星期一 星期二 星期三 星期四 星期五 星期六 下面是当月的各个时间 此函数返回该日历第一行星期日所在的日期
	 * 
	 * @param sdate
	 * @return
	 */
	public static String getNowMonth(String sdate) {
		// 取该时间所在月的一号
		sdate = sdate.substring(0, 8) + "01";

		// 得到这个月的1号是星期几
		Date date = DateUtils.strToDate(sdate);
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		int u = c.get(Calendar.DAY_OF_WEEK);
		String newday = DateUtils.getNextDay(sdate, (1 - u) + "");
		return newday;
	}
	/**
	 * 获得一个日期所在的周的星期几的日期，如要找出2015年2月3日所在周的星期一是几号
	 * 
	 * @param sdate
	 * @param num
	 * @return
	 */
	public static String getWeek(String sdate, String num) {
		// 再转换为时间
		Date dd = DateUtils.strToDate(sdate);
		Calendar c = Calendar.getInstance();
		c.setTime(dd);
		if (num.equals("1")) // 返回星期一所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		else if (num.equals("2")) // 返回星期二所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
		else if (num.equals("3")) // 返回星期三所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
		else if (num.equals("4")) // 返回星期四所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
		else if (num.equals("5")) // 返回星期五所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
		else if (num.equals("6")) // 返回星期六所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
		else if (num.equals("0")) // 返回星期日所在的日期
			c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
		return new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
	}
	/**
	 * 获取指定年份所有的月份
	 * @author zhuhuijun
	 * @date 2015年11月13日 下午2:58:55
	 * @param year  yyyy
	 * @return  yyyy-MM-dd 
	 */
	public static List<Date> getAllMonthFromYear(String year){
		if(year==null)return null;
		List<Date> ymdList=new ArrayList<Date>();
		String [] months={"01","02","03","04","05","06","07","08","09","10","11","12"};
		for(String mm : months){
			ymdList.add(DateUtils.strToDate(year+"-"+mm+"-01"));
		}
		return ymdList;
	}
	
	/**
	 * 获取指定月份的所有日期
	 * @author zhuhuijun
	 * @date 2015年11月13日 下午3:00:38
	 * @param date 
	 * @return
	 */
	public static List<String> getAllTheDateOftheMonth(Date date) {
		List<String> list = new ArrayList<String>();
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DATE, 1);

		int month = cal.get(Calendar.MONTH);
		while(cal.get(Calendar.MONTH) == month){
			list.add(dateToStr(cal.getTime()));
			cal.add(Calendar.DATE, 1);
		}
		return list;
	}
	/**
	 * 获取指定日期的当月周末(周六、周日)
	 * @author zhuhuijun
	 * @date 2015年11月13日 下午4:05:18
	 * @param date
	 * @return
	 */
	public static List<String> getCurrentMonthAllWeekend(Date date){
		List<String> months=getAllTheDateOftheMonth(date);
		List<String> weekendsList=new ArrayList<String>();
		for(String day : months){
			Date dd = DateUtils.strToDate(day);
			Calendar c = Calendar.getInstance();
			c.setTime(dd);
			int dayIndex = c.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
			if (dayIndex < 0){
				dayIndex = 0;
			}
			//周六和周日
			if(dayIndex==0||dayIndex==6){
				weekendsList.add(dateToStr(c.getTime()));
			}
		}
		return weekendsList;
	}
	
	/**
	 * 获取某年的所有日期
	 * @author zhuhuijun
	 * @date 2015年11月13日 下午3:03:39
	 * @param yyyy
	 * @return
	 */
	public static List<String> getAllDateOfTheYear(String yyyy){
		if(null==yyyy||yyyy.length()!=4)return null;
		List<String> dateStrList=new ArrayList<String>();
		List<Date> monthDates=DateUtils.getAllMonthFromYear(yyyy);
		for(Date month : monthDates){
			dateStrList.addAll(getAllTheDateOftheMonth(month));
		}
		return dateStrList;
	}
	/**
	 * 获取指定年份的所有周末(周六、周日)
	 * @author zhuhuijun
	 * @date 2015年11月13日 下午4:18:12
	 * @param dateStr yyyy
	 * @return
	 */
	public static List<String> getCurrentYearWeekends(String dateStr){
		List<String> dateStrList=new ArrayList<String>();
		List<Date> allMonthList= getAllMonthFromYear(dateStr);
		for(Date mDate : allMonthList){
			dateStrList.addAll(getCurrentMonthAllWeekend(mDate));
		}
		return dateStrList;
	}
	
	/** 
	 * 判断时间是否在时间段内 
	 *  
	 * @param date 
	 *            当前时间 yyyy-MM-dd HH:mm:ss 
	 * @param strDateBegin 
	 *            开始时间 00:00:00 
	 * @param strDateEnd 
	 *            结束时间 00:05:00 
	 * @return 
	 */ 
	public static boolean isInDate(Date date, String strDateBegin,  
	        String strDateEnd) {  
	    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
	    String strDate = sdf.format(date);  
	    // 截取当前时间时分秒  
	    int strDateH = Integer.parseInt(strDate.substring(11, 13));  
	    int strDateM = Integer.parseInt(strDate.substring(14, 16));  
	    int strDateS = Integer.parseInt(strDate.substring(17, 19));  
	    // 截取开始时间时分秒  
	    int strDateBeginH = Integer.parseInt(strDateBegin.substring(0, 2));  
	    int strDateBeginM = Integer.parseInt(strDateBegin.substring(3, 5));  
	    int strDateBeginS = Integer.parseInt(strDateBegin.substring(6, 8));  
	    // 截取结束时间时分秒  
	    int strDateEndH = Integer.parseInt(strDateEnd.substring(0, 2));  
	    int strDateEndM = Integer.parseInt(strDateEnd.substring(3, 5));  
	    int strDateEndS = Integer.parseInt(strDateEnd.substring(6, 8));  
	    
	    if((strDateH>=strDateBeginH && strDateH<=strDateEndH)){  
            if(strDateH>strDateBeginH && strDateH<strDateEndH){  
                return true;  
            }else if(strDateH==strDateBeginH && strDateM>strDateBeginM && strDateH<strDateEndH){  
                return true;  
            }else if(strDateH==strDateBeginH && strDateM==strDateBeginM && strDateS>strDateBeginS && strDateH<strDateEndH){  
                return true;  
            }else if(strDateH==strDateBeginH && strDateM==strDateBeginM && strDateS==strDateBeginS && strDateH<strDateEndH){  
                return true;  
            }else if(strDateH>strDateBeginH && strDateH==strDateEndH && strDateM<strDateEndM){  
                return true;  
            }else if(strDateH>strDateBeginH && strDateH==strDateEndH && strDateM==strDateEndM && strDateS<strDateEndS){  
                return true;  
            }else if(strDateH>strDateBeginH && strDateH==strDateEndH && strDateM==strDateEndM && strDateS==strDateEndS){  
                return true;  
            }else{  
                return false;  
            }  
            
        }else{  
            return false;  
        }  
	}  
	

//	public static void main(String[] args) {
////		List<String> list = geturrentYearWeekends("2016");
////			System.out.println(list);
////			System.out.println(list.size());
//	}
	
	public static int diffYear(Date d1, Date d2) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(d1);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
		return c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
	}

	public static int diffMonth(Date d1, Date d2) {
		Calendar c1 = Calendar.getInstance();
		c1.setTime(d1);
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
		int m = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
		int y = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
		return y * 12 + m;
	}

	public static int diffWeek(Date d1, Date d2) {
		int d = diffDay(d1, d2);
		if (d == 0)
			return 0;
		Calendar c2 = Calendar.getInstance();
		c2.setTime(d2);
		int w2 = c2.get(Calendar.DAY_OF_WEEK);
		if (c2.getFirstDayOfWeek() != Calendar.SUNDAY)
			w2 = (w2 == Calendar.SUNDAY) ? 7 : w2 - 1;
		int w = d / 7;
		int dw = (w2 + d % 7);
		if (dw < 1)
			return w - 1;
		if (dw > 7)
			return w + 1;
		return w;
	}

	public static int diffDay(Date d1, Date d2) {
		long offset =
			TimeZone.getDefault().getRawOffset()
				+ TimeZone.getDefault().getDSTSavings();
		return (int)
			((d1.getTime() + offset) / MILLIS_IN_DAY
				- (d2.getTime() + offset) / MILLIS_IN_DAY);
	}

	public static int diffHour(Date d1, Date d2) {
		return (int)
			(d1.getTime() / MILLIS_IN_HOUR - d2.getTime() / MILLIS_IN_HOUR);
	}

	public static int diffMinute(Date d1, Date d2) {
		return (int)
			(d1.getTime() / MILLIS_IN_MINUTE - d2.getTime() / MILLIS_IN_MINUTE);
	}

	public static int diffSecond(Date d1, Date d2) {
		return (int)
			(d1.getTime() / MILLIS_IN_SECOND - d2.getTime() / MILLIS_IN_SECOND);
	}

	public static Date roll(
		Date now,
		int year,
		int month,
		int day,
		int hour,
		int minute,
		int second) {
		Calendar c = Calendar.getInstance();
		c.setTime(now);
		c.add(Calendar.YEAR, year);
		c.add(Calendar.MONTH, month);
		c.add(Calendar.DATE, day);
		c.add(Calendar.HOUR_OF_DAY, hour);
		c.add(Calendar.MINUTE, minute);
		c.add(Calendar.SECOND, second);
		if (Date.class == now.getClass())
			return c.getTime();
		return newInstance(now.getClass(), c.getTimeInMillis());
	}

	public static Date rollTime(Date now, int hour, int minute, int second) {
		return roll(now, 0, 0, 0, hour, minute, second);
	}

	public static Date rollDate(Date now, int year, int month, int date) {
		return roll(now, year, month, date, 0, 0, 0);
	}
    
	public static Date rollDate (Date now,int day){
		Calendar c = Calendar.getInstance();
		c.setTime(now);
		c.add(Calendar.DATE, day);
		if (Date.class == now.getClass())
			return c.getTime();
		return newInstance(now.getClass(), c.getTimeInMillis());
	}
	public static Date rollWeek(Date now, int week, int day) {
		Calendar c = Calendar.getInstance();
		c.setTime(now);
		c.add(Calendar.WEEK_OF_YEAR, week);
		c.add(Calendar.DAY_OF_WEEK, day);
		if (Date.class == now.getClass())
			return c.getTime();
		return newInstance(now.getClass(), c.getTimeInMillis());
	}

	@SuppressWarnings("unchecked")
	private static Date newInstance(Class clazz, long newMillis) {
		try {
			Constructor c = clazz.getConstructor(new Class[] { long.class });
			Date d = (Date)c.newInstance(new Object[] { new Long(newMillis)});
			return d;
		} catch (Exception e) {
			return null;
		}
	}

	// ---------- general format and parse method -------------

	public static String format(Date date, String pattern) {
		String ret = null;
		SimpleDateFormat format = getDateFormat(pattern);
		ret = format.format(date);
		return ret;
	}
	public static String formatDate(Date date, String pattern) {
		if (date == null)
			return formatString("", pattern.length());
		SimpleDateFormat sdf = getDateFormat(pattern);
		return sdf.format(date);
	}
	public static String formatDatetime(Date date, String pattern) {
		if (date == null)
			return formatString("", pattern.length());
		SimpleDateFormat sdf = getDateFormat(pattern);
		return sdf.format(date);
	}
	public static Date parse(String dateStr, String pattern) {
		return parse(dateStr, pattern, null);
	}

	@SuppressWarnings("unchecked")
	public static Date parse(String dateStr, String pattern, Class clazz) {
		Date ret = null;

		try {
			SimpleDateFormat format = getDateFormat(pattern);
			ret = format.parse(dateStr);
		} catch (Exception e) {
//			log.warn(
//				"date format error! format:" + pattern + ",input:" + dateStr,
//				e);
			// slient skip exception, just return null;
			return null;
		}

		if (clazz == null || clazz == Date.class)
			return ret;
		return newInstance(clazz, ret.getTime());
	}

	

	public static String formatISODate(java.sql.Date date) {
		return getDateFormat(DATE_ISO_FORMAT).format(date);
	}
	public static String formatISODate(Date date) {
		return getDateFormat(DATE_ISO_FORMAT).format(date);
	}

	public static String formatISOTime(java.sql.Time time) {
		return getDateFormat(TIME_ISO_FORMAT).format(time);
	}
	

	public static String formatISODatetime(Timestamp timestamp) {
		return getDateFormat(DATETIME_ISO_FORMAT).format(timestamp);
	}

	public static String formatCompactDate(java.sql.Date date) {
		return getDateFormat(DATE_COMPACT_FORMAT).format(date);
	}
	public static String formatCompactDate(Date date) {
		return getDateFormat(DATE_COMPACT_FORMAT).format(date);
	}

	public static String formatCompactTime(java.sql.Time time) {
		return getDateFormat(TIME_COMPACT_FORMAT).format(time);
	}

	public static String formatCompactDatetime(Timestamp timestamp) {
		return getDateFormat(DATETIME_COMPACT_FORMAT).format(timestamp);
	}
	
	public static String formatCompactDatetime(Date date) {
		return getDateFormat(DATETIME_COMPACT_FORMAT).format(date);
	}
	public static String formatDateWithPattern(Object obj,String pattern){
		SimpleDateFormat sdf = getDateFormat(pattern);
		return sdf.format(obj);
	}

	public static java.sql.Date parseISODate(String dateStr) {
		return (java.sql.Date)parse(
			dateStr,
			getDateFormat(DATE_ISO_FORMAT),
			java.sql.Date.class);
	}
	public static Date parseDate(String dateStr){
		return (Date)parse(dateStr,getDateFormat(DATE_ISO_FORMAT),Date.class);
	}

	public static java.sql.Time parseISOTime(String timeStr) {
		return (java.sql.Time)parse(
			timeStr,
			getDateFormat(TIME_ISO_FORMAT),
			java.sql.Time.class);
	}

	public static Timestamp parseISODatetime(String dateStr) {
		return (Timestamp)parse(
			dateStr,
			getDateFormat(DATETIME_ISO_FORMAT),
			Timestamp.class);
	}



	public static java.sql.Date parseCompactDate(String dateStr) {
		return (java.sql.Date)parse(
			dateStr,
			getDateFormat(DATE_COMPACT_FORMAT),
			java.sql.Date.class);
	}

	public static java.sql.Time parseCompactTime(String timeStr) {
		return (java.sql.Time)parse(
			timeStr,
			getDateFormat(TIME_COMPACT_FORMAT),
			java.sql.Time.class);
	}

	public static Timestamp parseCompactDatetime(String dateStr) {
		return (Timestamp)parse(
			dateStr,
			getDateFormat(DATETIME_COMPACT_FORMAT),
			Timestamp.class);
	}
	public static Timestamp parseCompactDateFormat(String dateStr) {
		return (Timestamp)parse(
				dateStr+DATE_FORMAT,
				getDateFormat(DATETIME_COMPACT_FORMAT),
				Timestamp.class);
	}

	@SuppressWarnings("unchecked")
	private static Date parse(String dateStr, DateFormat format, Class clazz) {
		Date ret = null;

		try {
			ret = format.parse(dateStr);
			return newInstance(clazz, ret.getTime());
		} catch (ParseException e) {
			logger.warn(
				"date format error! format:"
					+ ((SimpleDateFormat)format).toPattern()
					+ ",input:"
					+ dateStr,
				e);
			// slient skip exception, just return null;
			return null;
		}

	}
	
	private static Calendar getCalendar(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c;
	}
	/**
	 * 获得年yyyy
	 * @param date
	 * @return
	 */
	public static int getYear(Date date) {
		return getCalendar(date).get(Calendar.YEAR);
	}
	/**
	 * 获得月MM
	 * @param date
	 * @return
	 */
	public static int getMonth(Date date) {
		return getCalendar(date).get(Calendar.MONTH) + 1;
	}
	/**
	 * 获得日dd
	 * @param date
	 * @return
	 */
	public static int getDay(Date date) {
		return getCalendar(date).get(Calendar.DAY_OF_MONTH);
	}
	public static final Calendar date2Calendar(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c;
	}

	public static boolean isMonth(Date batchDate) {
		if (batchDate == null) {
			return false;
		}
		Calendar c = date2Calendar(batchDate);
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DATE);
		if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8
				|| month == 10 || month == 12) {
			return day == 31;
		}
		if (month == 4 || month == 6 || month == 9 || month == 11) {
			return day == 30;
		}
		if (month == 2) {
			return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ? day == 29
					: day == 28;
		}
		return false;
	}

	public static boolean isQuarter(Date batchDate) {
		if (batchDate == null) {
			return false;
		}
		Calendar c = date2Calendar(batchDate);
//		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DATE);
		return (month == 3 && day == 31) || (month == 6 && day == 30)
				|| (month == 9 && day == 30) || (month == 12 && day == 31);
	}

	public static boolean isHalfyear(Date batchDate) {
		if (batchDate == null) {
			return false;
		}
		Calendar c = date2Calendar(batchDate);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DATE);
		return (month == 6 && day == 30) || (month == 12 && day == 31);
	}

	public static boolean isYear(Date batchDate) {
		if (batchDate == null) {
			return false;
		}
		Calendar c = date2Calendar(batchDate);
		int month = c.get(Calendar.MONTH) + 1;
		int day = c.get(Calendar.DATE);
		return (month == 12 && day == 31);
	}

//	public static void main(String[] args) {
//		System.out.println(DateUtils.getWeek("2015-11-13", "0"));
////		Date date = new Date(System.currentTimeMillis());
////		Timestamp tt = new Timestamp(System.currentTimeMillis());
////		System.err.println("hhmmss:"+DateUtils.formatDateWithPattern(tt,"hhmmss"));
////		System.err.println("yyyymmdd:"+DateUtils.formatDateWithPattern(date,"yymmdd"));
//		
////		TimeZone z = TimeZone.getDefault();
////		Date d1 = new Date();
////		java.sql.Date d2 =
////			new java.sql.Date(
////				System.currentTimeMillis() + 60000 * 60 * 43 + 34000);
////		d2 = (java.sql.Date)rollDate(d2, 3, 4, 1);
////		java.sql.Time t = new java.sql.Time(System.currentTimeMillis());
////		java.sql.Timestamp t1 =
////			new java.sql.Timestamp(System.currentTimeMillis());
////		System.err.println("compare:" + diffDay(d1, d2));
////		System.err.println("compare:" + diffHour(d1, d2));
////		System.err.println("compare:" + diffMinute(d1, d2));
////		System.err.println("compare:" + diffSecond(d1, d2));
////		System.err.println("compare:" + diffWeek(d1, d2));
////		System.err.println("compare:" + diffMonth(d1, d2));
////		System.err.println("compare:" + diffYear(d1, d2));
////
////		System.err.println("format:" + format(d2, "yyyy-MM-dd HH:mm:ss"));
////		System.err.println("format:" + formatCompactDate(d2));
////		System.err.println("format:" + formatCompactDatetime(t1));
////		System.err.println("format:" + formatCompactTime(t));
////		System.err.println("format:" + formatISODate(d2));
////		System.err.println("format:" + formatISODatetime(t1));
////		System.err.println("format:" + formatISOTime(t));
////
////		System.err.println(parse("2002-01-01 13:22:11", "yyyy-MM-dd HH:mm:ss"));
////		System.err.println(
////			parse("2002-01-01 13:22:11", "yyyy-MM-dd HH:mm:ss", Date.class));
////		System.err.println(parseISODate("2001-01-01"));
////		System.err.println(parseISOTime("23:46:11"));
////		System.err.println(parseISODatetime("2001-01-01 23:46:11"));
////
////		System.err.println(parseCompactDate("20010101"));
////		System.err.println(parseCompactTime("234611"));
////		System.err.println(parseCompactDatetime("20000101234611"));
////
////		System.err.println(rollDate(t1, 3, 0, 1));
////		System.err.println(rollTime(t1, -3, 4, 30));
////		System.err.println(rollWeek(t1, -3, 4));
////		
////		System.err.println(formatCompactDatetime(new Date()));
//
//	}
	public static final Timestamp toTimestamp(String str, String pattern) {
		SimpleDateFormat sdf = getDateFormat(pattern);
		try {
			return new Timestamp(sdf.parse(str).getTime());
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	final public static  java.sql.Date getTime(String time) {
		if (time == null) {
			return null;
		}
		int pos = time.indexOf(":");
		String strhour = time;
		String strminute = "0";
		if (pos != -1) {
			strhour = time.substring(0, pos);
			strminute = time.substring(pos + 1);
		}
		int hour = 0;
		int minute = 0;
		try {
			hour = Integer.parseInt(strhour);
			minute = Integer.parseInt(strminute);
		} catch (NumberFormatException e) {
			return null;
		}
		Calendar cd = Calendar.getInstance();
		cd.set(Calendar.HOUR_OF_DAY, hour);
		cd.set(Calendar.MINUTE, minute);
		return new java.sql.Date(cd.getTime().getTime());
	}
	
	public static String formatyyyymmddDatetime(Timestamp timestamp) {
		return getDateFormat(DATE_COMPACT_FORMAT).format(timestamp);
	}
	
	private static final Map<String, ThreadLocal<SimpleDateFormat>> pool = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
	private static final Object lock = new Object();
	
	private static ThreadLocal<SimpleDateFormat> sdf=new ThreadLocal<SimpleDateFormat>();
	
	public static SimpleDateFormat getDateFormat(String pattern) {
		ThreadLocal<SimpleDateFormat> tl = pool.get(pattern);
		if (tl == null) {
			synchronized (lock) {
				tl = pool.get(pattern);
				if (tl == null) {
					final String p = pattern;
					tl = new ThreadLocal<SimpleDateFormat>() {
						protected synchronized SimpleDateFormat initialValue() {
							return new SimpleDateFormat(p);
						}
					};
					pool.put(p, tl);
				}
			}
		}
		return tl.get();
/*		if(sdf.get()==null){
			sdf.set(new SimpleDateFormat());
		}
		SimpleDateFormat local=sdf.get();
		local.applyPattern(pattern);
		return local;*/
	}
	public static Timestamp getCurrentTimestamp() {
		return new Timestamp(System.currentTimeMillis());
	}

	private static String formatString(Object object, int len) {
		String str = (object == null) ? "" : object.toString().trim();

		while (str.getBytes().length > len) {
			str = str.substring(0, str.length() - 1);
		}

		int strLen = str.getBytes().length;

		str = str + repeat(" ", len - strLen);
		return str;
	}
	private static String repeat(String str, int num) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < num; i++) {
			buf.append(str);
		}
		return buf.toString();
	}
	
	/**
	 * 参数时间戳格式  
	 * @param str
	 * @return  yyyy-MM-dd
	 * @throws ParseException
	 */
	public static Date parseTimestampTime(String str) throws ParseException {
		SimpleDateFormat formatter = new SimpleDateFormat(DATE_ISO_FORMAT);
		String dateStr = formatter.format(Long.parseLong(str));
		return formatter.parse(dateStr);
	}
	/**
	 * <pre>校验日期是否合法</pre>
	 * @param dateStr
	 * @return
	 */
	public static boolean isISODateStr(String dateStr){		
		 Pattern p = Pattern.compile(DATE_ISO_PARTEN);
		 return p.matcher(dateStr).matches();
	}
	/**
	 * <pre>校验时间是否合法</pre>
	 * @param dateTimeStr
	 * @return
	 */
	public static boolean isISOTimeStr(String dateTimeStr){
		Pattern p = Pattern.compile(DATETIME_ISO_PARTEN);
		 return p.matcher(dateTimeStr).matches();		
	}
	/**
	 * 取上月末
	 * @param date
	 * @return
	 */
	public static Date getLastDateOfLastMonth(Date date){
		String dateString = format(date, DATE_ISO_FORMAT);
		Date dt = parse(dateString.substring(0, 8)+"01", DATE_ISO_FORMAT);
		Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.DAY_OF_MONTH,-1);
        return rightNow.getTime();
	}
	/**
	 * 取上月初
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfLastMonth(Date date){
		String dateString = format(date, DATE_ISO_FORMAT);
		Date dt = parse(dateString.substring(0, 8)+"01", DATE_ISO_FORMAT);
		Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);
        rightNow.add(Calendar.DAY_OF_MONTH,-1);
        return rightNow.getTime();
	}
	/**
	 * 取上月同期
	 * @param date
	 * @return
	 */
	public static Date getDateOfLastMonth(Date date){		 
		Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.MONTH,-1);
        return rightNow.getTime();
	}
	/**
	 * 取本月初
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfMonth(Date date){
		Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));  
        return c.getTime();  
	}
	 /** 
     * 取得月最后一天 
     *  
     * @param date 
     * @return 
     */  
    public static Date getLastDateOfMonth(Date date) {  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));  
        return c.getTime();  
    }  
    /** 
     * 取得季度第一天 
     *  
     * @param date 
     * @return 
     */  
    public static Date getFirstDateOfSeason(Date date) {  
        return getFirstDateOfMonth(getSeasonDate(date)[0]);  
    }  
  
    /** 
     * 取得季度最后一天 
     *  
     * @param date 
     * @return 
     */  
    public static Date getLastDateOfSeason(Date date) {  
        return getLastDateOfMonth(getSeasonDate(date)[2]);  
    }  
    
    /** 
     * 取得上季度季度第最后一天 
     *  
     * @param date 
     * @return 
     */  
    public static Date getLastDateOfLastSeason(Date date) {  
    	 return getLastDateOfLastMonth(getFirstDateOfSeason(date));   
    }  
    
    /** 
     * 取得季度月 
     *  
     * @param date 
     * @return 
     */  
    public static Date[] getSeasonDate(Date date) {  
        Date[] season = new Date[3];  
  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
  
        int nSeason = getSeason(date);  
        if (nSeason == 1) {// 第一季度  
            c.set(Calendar.MONTH, Calendar.JANUARY);  
            season[0] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.FEBRUARY);  
            season[1] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.MARCH);  
            season[2] = c.getTime();  
        } else if (nSeason == 2) {// 第二季度  
            c.set(Calendar.MONTH, Calendar.APRIL);  
            season[0] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.MAY);  
            season[1] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.JUNE);  
            season[2] = c.getTime();  
        } else if (nSeason == 3) {// 第三季度  
            c.set(Calendar.MONTH, Calendar.JULY);  
            season[0] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.AUGUST);  
            season[1] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.SEPTEMBER);  
            season[2] = c.getTime();  
        } else if (nSeason == 4) {// 第四季度  
            c.set(Calendar.MONTH, Calendar.OCTOBER);  
            season[0] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.NOVEMBER);  
            season[1] = c.getTime();  
            c.set(Calendar.MONTH, Calendar.DECEMBER);  
            season[2] = c.getTime();  
        }  
        return season;  
    }  
    /**
	 * 取本年初
	 * @param date
	 * @return
	 */
	public static Date getFirstDateOfYear(Date date){
		Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        c.set(Calendar.DAY_OF_YEAR, c.getActualMinimum(Calendar.DAY_OF_YEAR));  
        return c.getTime();  
	}
	 /** 
     * 取本年末
     *  
     * @param date 
     * @return 
     */  
    public static Date getLastDateOfYear(Date date) {  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        c.set(Calendar.DAY_OF_YEAR, c.getActualMaximum(Calendar.DAY_OF_YEAR));  
        return c.getTime();  
    }
	 /** 
     * 取上年末
     *  
     * @param date 
     * @return 
     */  
    public static Date getLastDateOfLastYear(Date date) {  
        return getLastDateOfLastMonth(getFirstDateOfYear(date));
    }   
    /** 
     * 取去年同期
     *  
     * @param date 
     * @return 
     */  
    public static Date getDateOfLastYear(Date date) {  
    	Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.YEAR,-1);
        return rightNow.getTime();
    }  
    /** 
     * 取得当天日期是周几 
     *  
     * @param date 
     * @return 
     */  
    public static int getWeekDay(Date date) {  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        int week_of_year = c.get(Calendar.DAY_OF_WEEK);  
        return week_of_year - 1;  
    } 
    /** 
     * 当前日期加几天
     *  
     * @param date 
     * @return 
     */  
    public static Date addDays(Date date,int days) {  
    	Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(date);
        rightNow.add(Calendar.DAY_OF_MONTH,days);
        return rightNow.getTime();
    } 
    /** 
     *  
     * 1 第一季度 2 第二季度 3 第三季度 4 第四季度 
     *  
     * @param date 
     * @return 
     */  
    public static int getSeason(Date date) {  
  
        int season = 0;  
  
        Calendar c = Calendar.getInstance();  
        c.setTime(date);  
        int month = c.get(Calendar.MONTH);  
        switch (month) {  
        case Calendar.JANUARY:  
        case Calendar.FEBRUARY:  
        case Calendar.MARCH:  
            season = 1;  
            break;  
        case Calendar.APRIL:  
        case Calendar.MAY:  
        case Calendar.JUNE:  
            season = 2;  
            break;  
        case Calendar.JULY:  
        case Calendar.AUGUST:  
        case Calendar.SEPTEMBER:  
            season = 3;  
            break;  
        case Calendar.OCTOBER:  
        case Calendar.NOVEMBER:  
        case Calendar.DECEMBER:  
            season = 4;  
            break;  
        default:  
            break;  
        }  
        return season;  
    }      
    public static String getUniqueKey() {  
    	SimpleDateFormat formatter =getDateFormat(DATETIME_SYSKEY_FORMAT); 
    	return formatter.format(new Date(System.currentTimeMillis()))+randomWithLen(3);
      
    }
    public static String randomWithLen(int len){
    	int m = (int)Math.pow(10, len-1);
    	int i=(int)(Math.random()*m*9)+m; 
    	return String.valueOf(i);
    }
    
    /**
     * 获取给定时间后n分钟的时间
     * @param date
     * @param minute  分钟
     * @return
     */
    public static Date getMinuteAfter(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }
}
